package com.mzy.basics.utils.Io;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author mzy
 * @Date 2022/4/9 0:37
 * @Version 1.0
 */
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author mzy
 * @Date 2022/4/16 15:23
 * @Version 1.0
 */

@Slf4j
public class FileUtil {

    private FileUtil() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 写内容
     *
     * @param byteArr  内容
     * @param filePath 文件路径
     * @return
     */
    public static void writeByteArrFile(byte[] byteArr, String filePath) {
        try {
            if (byteArr != null) {
                File file = new File(filePath);
                if (file.exists()) {
                    file.delete();
                }
                try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
                    fileOutputStream.write(byteArr, 0, byteArr.length);
                    fileOutputStream.flush();
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过文件名和文件路径下载指定文件
     *
     * @param response
     * @param folderName
     * @param fileName
     */
    public static void downloadFile(HttpServletResponse response, String folderName, String fileName) {

        try {

            String logPath = folderName + File.separator + fileName;
            // 读文件
            File file = new File(logPath);
            // 重置response
            response.reset();
            // ContentType，即告诉客户端所发送的数据属于什么类型
            response.setContentType("application/octet-stream; charset=UTF-8");
            // 获得文件的长度
            response.setHeader("Content-Length", String.valueOf(file.length()));
            // 设置编码格式
            response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);

            // 发送给客户端的数据
            try (OutputStream outputStream = response.getOutputStream();
                 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));) {

                byte[] buff = new byte[1024];
                int i = bis.read(buff);
                // 只要能读到，则一直读取
                while (i != -1) {
                    // 将文件写出
                    outputStream.write(buff, 0, buff.length);
                    // 刷出
                    i = bis.read(buff);
                }
                outputStream.flush();
            }
        } catch (Exception e) {
            log.error("下载文件异常", e);
        }
    }

    /**
     * 删除指定目录下的文件
     *
     * @param filePath
     */
    public static boolean deleteFile(String filePath) {
        File file = new File(filePath);
        return delFile(file);
    }

    /**
     * 删除文件传入File
     *
     * @param file
     * @return
     */
    public static boolean delFile(File file) {
        if (!file.exists()) {
            return false;
        }

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (File f : files) {
                delFile(f);
            }
        }
        return file.delete();
    }

    /**
     * 下载前端传过来的文件到指定路径
     *
     * @param file
     * @return
     * @throws IOException
     */
    public static Boolean fileUpload(@RequestParam("file") MultipartFile file, String filePath) {
        try {
            if (file.isEmpty()) {
                return false;
            }
            String fileName = file.getOriginalFilename();
            File fileTem = new File(new File(filePath).getAbsolutePath() + File.separator + fileName);
            if (!fileTem.getParentFile().exists()) {
                fileTem.getParentFile().mkdirs();
            }

            file.transferTo(fileTem); // 保存文件
            return true;
        } catch (Exception e) {
            log.error("下载文件异常", e);
            return false;
        }
    }


    /**
     * 读取文件内容
     *
     * @param path
     * @return
     */
    public static String readFile(String path) {
        File file = new File(path);
        byte[] data = new byte[0];
        if (file.exists() && file.isFile()) {
            try {
                data = Files.readAllBytes(file.toPath());
            } catch (IOException e) {
                log.warn("file read error", e);
            }
        }
        return new String(data, StandardCharsets.UTF_8);
    }

    public static boolean mkDirs(String dirPath) {
        File file = new File(dirPath);
        if (!file.exists())
            return file.mkdirs();
        return file.isDirectory();
    }

    public static boolean createFile(String destFileName) {

        try {
            File file = new File(destFileName);
            //判断目标文件所在的目录是否存在
            if(!file.getParentFile().exists()) {
                //如果目标文件所在的目录不存在，则创建父目录
                file.getParentFile().mkdirs();
            }
            if (file.exists()) {
                return true;
            }
            //创建目标文件
            return file.createNewFile();
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 创建文件
     * @param fileName 文件名称
     * @param filePath 文件路径
     * @return
     */
    public static boolean createFile(String filePath, String fileName) {
        mkDirs(filePath);
        File file = new File(filePath + File.separator + fileName);
        try {
            if (!file.exists()) {
                return file.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 写内容
     *
     * @param content 内容
     * @param filePath 文件路径
     * @return
     */
    public static void writeContent(String content, String filePath) {
        File file = new File(filePath);
        try(
                FileOutputStream fileOutputStream = new FileOutputStream(file, true);
                Writer write = new OutputStreamWriter(fileOutputStream, StandardCharsets.UTF_8);
        ) {
            // 将内容写入文件
            write.write(content);
            write.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 收集路径下所有文件
     * @param fileList
     * @param path
     * @return
     */
    public static void collectFileList (List<File> fileList, String path) {
        File file = new File(path);
        for (File sysFile : file.listFiles()) {
            if (sysFile.isDirectory()) {
                collectFileList(fileList, sysFile.getAbsolutePath());
            } else
                fileList.add(sysFile);
        }
    }

    /**
     * 把文件压缩成zip包，下载到浏览器
     * @param fileList
     * @param response
     * @throws IOException
     */
    public static void fileToZip(List<File> fileList, HttpServletResponse response) throws IOException{
        try (
                ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
        ) {
            for(int i = 0; i < fileList.size(); i++){
                //创建ZIP实体，并添加进压缩包
                ZipEntry zipEntry = new ZipEntry(fileList.get(i).getName());
                zos.putNextEntry(zipEntry);
                //读取待压缩的文件并写进压缩包里
                zipFile(fileList.get(i), zos);
            }
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("content-type", "application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", new String(("MIB.zip").getBytes(), StandardCharsets.UTF_8));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            response.flushBuffer();
        }
    }

    private static void zipFile (File file, ZipOutputStream zos) {
        try (
                FileInputStream fis = new FileInputStream(file);
                BufferedInputStream bis = new BufferedInputStream(fis, 1024*10)
        ) {
            byte[] bufs = new byte[1024*10];
            int read = 0;
            while((read=bis.read(bufs, 0, 1024*10)) != -1){
                zos.write(bufs,0,read);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 写入文件
     *
     * @param data
     * @param url
     * @return
     */
    public static long saveFile(String data, String url) {
        try {
            byte[] da = data.getBytes(StandardCharsets.UTF_8);
            Path path = Paths.get(url);
            Files.write(path, da);
            return Files.size(path);
        } catch (UnsupportedEncodingException e) {
            log.warn("string coding error", e);
            return -1;
        } catch (IOException e) {
            log.warn(" write fail ", e);
            return -1;
        }
    }


}